﻿// **************************************************
// This file created by Brett Bibby (c) 2010-2013
// You may freely use and modify this file as you see fit
// You may not sell it
//**************************************************
// hidden object game exporter
//$.writeln("=== Starting Debugging Session ===");

// enable double clicking from the Macintosh Finder or the Windows Explorer
#target photoshop

// debug level: 0-2 (0:disable, 1:break on error, 2:break at beginning)
// $.level = 0;
// debugger; // launch debugger on next line


/*
 * 类型: PS -> Unity类型映射
 * 文本:TextItem -> UGUI(Text)
 * 图层:ArtLayer -> UGUI(Image)
 * 组别:LayerSet -> UGUI(Rect Transform)
 */
var Component = {
    TextItem : "TextItem",
    ArtLayer : "ArtLayer",
    LayerSet : "LayerSet",
}

/**
 *string:原始字符串
 *substr:子字符串
 *isIgnoreCase:忽略大小写
 */
function contains(string, substr, isIgnoreCase) {
    if (isIgnoreCase) {
        string = string.toLowerCase();
        substr = substr.toLowerCase();
    }
    var startChar = substr.substring(0, 1);
    var strLen = substr.length;
    for (var j = 0; j < string.length - strLen + 1; j++) {
        if (string.charAt(j) == startChar) //如果匹配起始字符,开始查找
        {
            if (string.substring(j, j + strLen) == substr) //如果从j开始的字符与str匹配，那ok
        {
            return true;
        }
        }
    }
    return false;
}

//"#ffffff".colorRgb();  // rgb(255,255,255)
String.prototype.colorRgb = function () {
    // 16进制颜色值的正则
    var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
    // 把颜色值变成小写
    var color = this.toLowerCase();
    if (reg.test(color)) {
        // 如果只有三位的值，需变成六位，如：#fff => #ffffff
        if (color.length === 4) {
        var colorNew = "#";
        for (var i = 1; i < 4; i += 1) {
            colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1));
        }
        color = colorNew;
        }
        // 处理六位的颜色值，转为RGB
        var colorChange = [];
        for (var i = 1; i < 7; i += 2) {
        colorChange.push(parseInt("0x" + color.slice(i, i + 2)));
        }
        return colorChange.join(",");
    } else {
        return color;
    }
}

/**
 * 计算边距
 */
function calcMargin(x, y, w, h) {
    x = Number(x)
    y = Number(y)
    w = Number(w)
    h = Number(h)
    //var doc = app.activeDocument;
    //var width = doc.width;
    //var height = doc.height;
    //top, left, btom, rght
    var top = 0 + y;
    var left = 0 + x;
    var btom = top + h;
    var rght = left + w;
    return [ top, left, btom, rght ]
}

/*
var creatNewDocument = function (width, height, resolution, docName) {
    alert(docName);
    //使用photoshop api创建文档
    app.documents.add(width, height, resolution, docName);
}
*/

function checkInvalidLayer() {
    // got a valid document?
    if (app.documents.length <= 0)
    {
        if (app.playbackDisplayDialogs != DialogModes.NO)
        {
            alert("You must have a document open to export!");
        }
        // quit, returning 'cancel' makes the actions palette not record our script
        return null;
    }

    var document = app.activeDocument;
    if (!document)
    {
        alert("You must active a document");
        return null;
    }

    var layer = document.activeLayer;//活动图层
    if (layer == null || typeof(layer) == "undefined")
    {
        alert("You must active a layer");
        return null;
    }

    if (!layer.name)
    {
        alert("activeLayer name is null");
        return null;
    }

    return layer;
}

/**
 * 生成新名称
 * AAA_AAA_BBB@CCC 有可能是这样的
 * ‘@’属性暂时支持一个 ‘_’属性可以有多个
 */
function genNewAttrName(attr, value, orgi_name) {
    var attr_value = value;
    var name_split = [];
    var new_name = "";
    // 此种属性直接设置并且抹掉名称
    if (attr_value == "@Size")
    {
        new_name = attr_value;
    }
    else
    {        
        // 包含直接替换为空
        if (contains(orgi_name, attr_value))
        {
            new_name = orgi_name.replace(attr_value, "")
        }
        else
        {
            // 没有@新增到后面
            if (contains(attr_value, "@"))
            {
                new_name = orgi_name + attr_value;
            }
            else
            {
                name_split = orgi_name.split("@");
                for (var index = 0; index < name_split.length; index++) {
                    var element = name_split[index];
                    // 没有_新增到后面
                    if (index == 0)
                    {
                        new_name = element + attr_value;
                    }
                    // 剩余的链接起来
                    else
                    {
                        new_name = new_name + "@" + element;
                    }
                }
            }
        }
    }

    return new_name;
}

/**
 * 设置属性
 */
function reSetAttrValue(attr, value) {
    var layer = checkInvalidLayer();
    if (layer == null || typeof(layer) == "undefined")
    {
        return 'cancel';
    }

    var orgi_name = layer.name;
    var new_name = genNewAttrName(attr, value, orgi_name);

    if (new_name == "")
    {
        alert ("new name is none.");
        return 'cancel';
    }

    try
    {
        layer.name = new_name;
    }
    catch (e)
    {
        alert (e);
        return 'cancel';
    }

    return 'ok!';
}

/**
 * 创建组
 */
function createGroup(node, name) {
    var typename = node.typename;
    if (typename == Component.ArtLayer) {
        return null;
    }
    var group = node.layerSets.add();
    group.name = name;
    return group;
}

/**
 * 创建层
 */
function createLayer(node, name) {
    var typename = node.typename;
    if (typename == Component.ArtLayer) {
        return null;
    }
    var layer = node.artLayers.add();
    layer.name = name;
    return layer;
}

/**
 * 创建图片
 */
function createImage(node, name, attr) {
    var newLayer = createLayer(node, name);
    var attrs = attr.split(":");
    var params = []
    if (attrs.length >= 2) {
        params = attrs[1].split(",");
    }
    var x = params[0] ? params[0] : '0';
    var y = params[1] ? params[1] : '0';
    var w = params[2] ? params[2] : '0';
    var h = params[3] ? params[3] : '0';
    var color = "#" + (params[4] ? params[4] : 'ffffff');
    var s_color = color.colorRgb();
    var colors  = s_color.split(",");
    var r = colors[0] ? colors[0] : '0';
    var g = colors[1] ? colors[1] : '0';
    var b = colors[2] ? colors[2] : '0';
    var margin = calcMargin(x, y, w, h);
    var top  = margin[0];
    var left = margin[1];
    var btom = margin[2];
    var rght = margin[3];
    createRoundedRectangle(top, left, btom, rght, r, g, b);
    return newLayer;
}

/**
 * 创建文本
 * 'TextItem:10,10,20,ffffff,我是文本'
 */
function createLabel(node, name, attr) {
    var newLayer = createLayer(node, name);
    var attrs = attr.split(":");
    var params = []
    if (attrs.length >= 2) {
        params = attrs[1].split(",");
    }
    var x = params[0] ? params[0] : '0';
    var y = params[1] ? params[1] : '0';
    var size = params[2] ? params[2] : '30';
    var color = params[3] ? params[3] : 'ffffff';
    var text = params[4] ? params[4] : 'NormalText';
    createLabelAttr(newLayer, x, y, size, color, text);
    return newLayer;
}

/**
 * 创建文本属性
 * newLayer:图层 x:"10 px" y:"10 px" size:"30 pt" color:hex颜色"FFFFFF" text:内容
 */
function createLabelAttr(newLayer, x, y, size, color, text) {
    //x = Number(x) + " px";
    var h = Number(size) + " px";
    var w =  Number(size) * text.length + " px";
    x = Number(x);
    //y = Number(y) + " px";
    y = Number(y);
    size = Number(size) + " pt";
    var font = "Arial";
    //把图层 newLayer 的图层类型变为”文本“ ，图层转换为文本图层。
    newLayer.kind = LayerKind.TEXT;
    var textItem = newLayer.textItem;
    newLayer.textItem.font = font;
    //把图层 newLayer 的文本内容类型变为”点文本，没有文本框“。TextType.POINTTEXT / TextType.PARAGRAPHTEXT
    newLayer.textItem.kind = TextType.POINTTEXT;
    //设置 newLayer 的文本字体大小为“30 点”。
    newLayer.textItem.size = UnitValue(size);
    //设置 newLayer 的文本内容。
    newLayer.textItem.contents= text;
    //设置 newLayer 的文本框对齐方式为左对齐。
    newLayer.textItem.justification = Justification.LEFT;
    //创建一个色彩变量 c   ，颜色为 #FFFFFF。
    var c = new SolidColor();
    c.rgb.hexValue = color;
    //设置 newLayer 的文本颜色为 c。
    newLayer.textItem.color = c;
    //设置图层 newLayer 的文本框位置，横坐标 375 像素，纵坐标 667 像素。
    //这个位置修改了不对头
    newLayer.textItem.position = Array(x, y);
    //设置图层 newLayer 的文本框宽度与高度。
    //newLayer.textItem.width = w;
    //newLayer.textItem.height = h;
    //var margin = calcMargin(x, y, w, h);
    //newLayer.bounds = margin;
}

/**
 * 创建圆角矩形
 * top:上 left:左 btom:下 rght:右 rgb
 * createRoundedRectangle(522, 120, 614, 658, 200, 200, 200)
 */
function createRoundedRectangle(top, left, btom, rght, r, g, b) {
    top  = Number(top)
    left = Number(left)
    btom = Number(btom)
    rght = Number(rght)
    r = Number(r)
    g = Number(g)
    b = Number(b)
    var idMk = charIDToTypeID( "Mk  " );
    var desc18 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
    var ref10 = new ActionReference();
    var idcontentLayer = stringIDToTypeID( "contentLayer" );
    ref10.putClass( idcontentLayer );
    desc18.putReference( idnull, ref10 );
    var idUsng = charIDToTypeID( "Usng" );
    var desc19 = new ActionDescriptor();
    var idType = charIDToTypeID( "Type" );
    var desc20 = new ActionDescriptor();
    var idClr = charIDToTypeID( "Clr " );
    var desc21 = new ActionDescriptor();
    var idRd = charIDToTypeID( "Rd  " );
    desc21.putDouble( idRd, r );
    var idGrn = charIDToTypeID( "Grn " );
    desc21.putDouble( idGrn, g );
    var idBl = charIDToTypeID( "Bl  " );
    desc21.putDouble( idBl, b );
    var idRGBC = charIDToTypeID( "RGBC" );
    desc20.putObject( idClr, idRGBC, desc21 );
    var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
    desc19.putObject( idType, idsolidColorLayer, desc20 );
    var idShp = charIDToTypeID( "Shp " );
    var desc22 = new ActionDescriptor();
    var idunitValueQuadVersion = stringIDToTypeID( "unitValueQuadVersion" );
    desc22.putInteger( idunitValueQuadVersion, 1 );
    var idTop = charIDToTypeID( "Top " );
    var idPxl = charIDToTypeID( "#Pxl" );
    desc22.putUnitDouble( idTop, idPxl, top );
    var idLeft = charIDToTypeID( "Left" );
    var idPxl = charIDToTypeID( "#Pxl" );
    desc22.putUnitDouble( idLeft, idPxl, left );
    var idBtom = charIDToTypeID( "Btom" );
    var idPxl = charIDToTypeID( "#Pxl" );
    desc22.putUnitDouble( idBtom, idPxl, btom );
    var idRght = charIDToTypeID( "Rght" );
    var idPxl = charIDToTypeID( "#Pxl" );
    desc22.putUnitDouble( idRght, idPxl, rght );
    var idtopRight = stringIDToTypeID( "topRight" );
    var idPxl = charIDToTypeID( "#Pxl" );
    desc22.putUnitDouble( idtopRight, idPxl, 10.000000 );
    var idtopLeft = stringIDToTypeID( "topLeft" );
    var idPxl = charIDToTypeID( "#Pxl" );
    desc22.putUnitDouble( idtopLeft, idPxl, 10.000000 );
    var idbottomLeft = stringIDToTypeID( "bottomLeft" );
    var idPxl = charIDToTypeID( "#Pxl" );
    desc22.putUnitDouble( idbottomLeft, idPxl, 10.000000 );
    var idbottomRight = stringIDToTypeID( "bottomRight" );
    var idPxl = charIDToTypeID( "#Pxl" );
    desc22.putUnitDouble( idbottomRight, idPxl, 10.000000 );
    var idRctn = charIDToTypeID( "Rctn" );
    desc19.putObject( idShp, idRctn, desc22 );
    var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
    var desc23 = new ActionDescriptor();
    var idstrokeStyleVersion = stringIDToTypeID( "strokeStyleVersion" );
    desc23.putInteger( idstrokeStyleVersion, 2 );
    var idstrokeEnabled = stringIDToTypeID( "strokeEnabled" );
    desc23.putBoolean( idstrokeEnabled, false );
    var idfillEnabled = stringIDToTypeID( "fillEnabled" );
    desc23.putBoolean( idfillEnabled, true );
    var idstrokeStyleLineWidth = stringIDToTypeID( "strokeStyleLineWidth" );
    var idPxl = charIDToTypeID( "#Pxl" );
    desc23.putUnitDouble( idstrokeStyleLineWidth, idPxl, 1.000000 );
    var idstrokeStyleLineDashOffset = stringIDToTypeID( "strokeStyleLineDashOffset" );
    var idPnt = charIDToTypeID( "#Pnt" );
    desc23.putUnitDouble( idstrokeStyleLineDashOffset, idPnt, 0.000000 );
    var idstrokeStyleMiterLimit = stringIDToTypeID( "strokeStyleMiterLimit" );
    desc23.putDouble( idstrokeStyleMiterLimit, 100.000000 );
    var idstrokeStyleLineCapType = stringIDToTypeID( "strokeStyleLineCapType" );
    var idstrokeStyleLineCapType = stringIDToTypeID( "strokeStyleLineCapType" );
    var idstrokeStyleButtCap = stringIDToTypeID( "strokeStyleButtCap" );
    desc23.putEnumerated( idstrokeStyleLineCapType, idstrokeStyleLineCapType, idstrokeStyleButtCap );
    var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
    var idstrokeStyleLineJoinType = stringIDToTypeID( "strokeStyleLineJoinType" );
    var idstrokeStyleMiterJoin = stringIDToTypeID( "strokeStyleMiterJoin" );
    desc23.putEnumerated( idstrokeStyleLineJoinType, idstrokeStyleLineJoinType, idstrokeStyleMiterJoin );
    var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
    var idstrokeStyleLineAlignment = stringIDToTypeID( "strokeStyleLineAlignment" );
    var idstrokeStyleAlignInside = stringIDToTypeID( "strokeStyleAlignInside" );
    desc23.putEnumerated( idstrokeStyleLineAlignment, idstrokeStyleLineAlignment, idstrokeStyleAlignInside );
    var idstrokeStyleScaleLock = stringIDToTypeID( "strokeStyleScaleLock" );
    desc23.putBoolean( idstrokeStyleScaleLock, false );
    var idstrokeStyleStrokeAdjust = stringIDToTypeID( "strokeStyleStrokeAdjust" );
    desc23.putBoolean( idstrokeStyleStrokeAdjust, false );
    var idstrokeStyleLineDashSet = stringIDToTypeID( "strokeStyleLineDashSet" );
    var list6 = new ActionList();
    desc23.putList( idstrokeStyleLineDashSet, list6 );
    var idstrokeStyleBlendMode = stringIDToTypeID( "strokeStyleBlendMode" );
    var idBlnM = charIDToTypeID( "BlnM" );
    var idNrml = charIDToTypeID( "Nrml" );
    desc23.putEnumerated( idstrokeStyleBlendMode, idBlnM, idNrml );
    var idstrokeStyleOpacity = stringIDToTypeID( "strokeStyleOpacity" );
    var idPrc = charIDToTypeID( "#Prc" );
    desc23.putUnitDouble( idstrokeStyleOpacity, idPrc, 100.000000 );
    var idstrokeStyleContent = stringIDToTypeID( "strokeStyleContent" );
    var desc24 = new ActionDescriptor();
    var idClr = charIDToTypeID( "Clr " );
    var desc25 = new ActionDescriptor();
    var idRd = charIDToTypeID( "Rd  " );
    desc25.putDouble( idRd, 0.000000 );
    var idGrn = charIDToTypeID( "Grn " );
    desc25.putDouble( idGrn, 0.000000 );
    var idBl = charIDToTypeID( "Bl  " );
    desc25.putDouble( idBl, 0.000000 );
    var idRGBC = charIDToTypeID( "RGBC" );
    desc24.putObject( idClr, idRGBC, desc25 );
    var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );
    desc23.putObject( idstrokeStyleContent, idsolidColorLayer, desc24 );
    var idstrokeStyleResolution = stringIDToTypeID( "strokeStyleResolution" );
    desc23.putDouble( idstrokeStyleResolution, 72.000000 );
    var idstrokeStyle = stringIDToTypeID( "strokeStyle" );
    desc19.putObject( idstrokeStyle, idstrokeStyle, desc23 );
    var idcontentLayer = stringIDToTypeID( "contentLayer" );
    desc18.putObject( idUsng, idcontentLayer, desc19 );
    var idLyrI = charIDToTypeID( "LyrI" );
    desc18.putInteger( idLyrI, 36 );
    try {
        executeAction( idMk, desc18, DialogModes.NO );
    } catch (error) {
        alert(error);
    }
}

/**
 * 递归创建节点
 */
function createWalkNode(map, parent) {
    if (parent == null || typeof(parent) == "undefined") {
        return;
    }

    for (var k in map) {
        if (map.hasOwnProperty(k)) {
            var name = k;
            var val = map[k];
            if (typeof(val) == "string")
            {
                if (contains(val, Component.ArtLayer)) {
                    createImage(parent, name, val);
                }
                else if (contains(val, Component.TextItem)) {
                    createLabel(parent, name, val);
                }
            }
            else if (typeof(val) == "object")
            {
                var p = createGroup(parent, name);
                createWalkNode(val, p);
            }
        }
    }
}

/**
 * 创建节点
 */
function createPsdNode(json) {
    var layer = checkInvalidLayer();
    if (layer == null || typeof(layer) == "undefined")
    {
        return 'cancel';
    }

    //alert(json)
    //LayerSet ArtLayer
    var typename = layer.typename;
    if (typename != Component.LayerSet) {
        layer = layer.parent;
    }

    var map = JSON.parse(json);
    createWalkNode(map, layer);
    return 'ok!';
}

function main(){
        // got a valid document?
    if (app.documents.length <= 0)
    {
        if (app.playbackDisplayDialogs != DialogModes.NO)
        {
            alert("You must have a document open to export!");
        }
        // quit, returning 'cancel' makes the actions palette not record our script
        return 'cancel';
    }

    //setTool("typeCreateOrEditTool");

    var documents = app.documents;
    var doc = app.activeDocument;
    var layer = doc.activeLayer;
    
    createLabel(layer, "hahaha", "TextItem:340,320,30,ffffff,默认文本");
    createLabel(layer, "hahaha", "TextItem:173,320,30,ffffff,默认文本");
    createLabel(layer, "hahaha", "TextItem:450,320,30,ffffff,默认文本");
}

main();